package com.example.readexceldata.util;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.readexceldata.dto.WatchImportData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * @Description
 * @Author Administrator
 * @Date 2024/9/5 10:03
 * @Version
 **/

@Slf4j
public class WatchImportDataListener extends AnalysisEventListener<WatchImportData> {

    /**
     * 缓存的数据
     */
    private List<WatchImportData> cachedDataList = new ArrayList<>();
    private List<String> errorLog = new ArrayList<>();

    private IService iService;

    /**
     * 是否校验模板标题（默认false）
     */
    private boolean isValidationHead;

    /**
     * 导入模板表头集合(需要校验)
     */
    private List<String> titleList;


    /**
     * 导入模板表头集合
     */
    private List<String> ImportTitleList=new ArrayList<>();

    /**
     * 数据总条数
     */
    private int count;

    /**
     * 信息提示
     */
    private String msg="";



    /**
     * 错误信息集合 map
     * （key-行数，value-错误信息）
     */
    private Map<Integer, String> errMap = new HashMap<>();


    public WatchImportDataListener(IService iService) {
        this.iService = iService;
        this.isValidationHead = false;
    }


    public WatchImportDataListener(IService iService, List<String> titleList) {
        this.isValidationHead = true;
        this.iService = iService;
        this.titleList = titleList;
    }




    /**
     * 每一条数据解析都会来调用
     *
     * @param o
     * @param analysisContext
     */
    @Override
    public void invoke(WatchImportData o, AnalysisContext analysisContext) {
        log.info("解析到一条数据:{}", JSON.toJSONString(o));
        if (msg.isEmpty()) {
            cachedDataList.add(o);
        }
    }


        /**
         * 所有数据解析完成了 都会来调用
         *
         * @param analysisContext
         */
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext){
            // 存储最后的数据（剩下的数据少于指定的条数）
            if (!errorLog.isEmpty()) {
            }
            saveData();
            log.info("所有数据解析完成！");
            msg = String.format("导入成功，成功导入数据 %d 条", cachedDataList.size());
        }

        @Override
        public boolean hasNext (AnalysisContext context){
            return super.hasNext(context);
        }


        /**
         * 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
         *
         * @param exception
         * @param context
         * @throws Exception
         */
        @Override
        public void onException (Exception exception, AnalysisContext context) throws Exception {
//        log.error("解析失败，但是继续解析下一行，异常信息:{}", exception.getMessage());
            // 如果是某一个单元格的转换异常 能获取到具体行号
            // 如果要获取头的信息 配合invokeHeadMap使用
            if (exception instanceof ExcelDataConvertException) {
                ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
//            log.error("第{}行，第{}列解析异常，数据为:{}", excelDataConvertException.getRowIndex(),
//                    excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData().getStringValue());
                String format = String.format("第【%s】行，第【%s】列解析异常，数据为：%s，异常为：%s", excelDataConvertException.getRowIndex() + 1,
                        excelDataConvertException.getColumnIndex() + 1, excelDataConvertException.getCellData().getStringValue(), excelDataConvertException.getMessage());
                excelDataConvertException.printStackTrace();
                errorLog.add(format);
            } else {
                exception.printStackTrace();
            }
        }


        /**
         * 分析表头
         * TODO 目前仅能对多表头的最后一行的表头进行必要表头判断，若存在必要表头存在于其他行内，则无法进行判断
         *
         * @param headMap
         * @param context
         */
        @Override
        public void invokeHeadMap (Map < Integer, String > headMap, AnalysisContext context){
            System.out.println("表头行数：" + headMap.toString());
            headMap.forEach((k, v) -> {
                if (v != null) {
                    ImportTitleList.add(v);
                }
            });
            String msg = "";

            if (!StringUtils.isBlank(msg)) {
                msg = "原因：导入模板中缺少以下列：" + msg.substring(0, msg.length() == 0 ? 0 : msg.length() - 1);
            }
        }


        /**
         * 加上存储数据库
         */
        private void saveData() {
//            if (iService instanceof WatchService watchService) {
//                Map<String, String> map= watchService.importSaveData(cachedDataList);
//                errorLog.add(map.get("successCount"));
//                msg = String.join("", errorLog);
//                log.info("[excel导入]存储数据库成功！");
//
//            }

    }

    @Override
    public void extra(CellExtra extra, AnalysisContext context) {
        super.extra(extra, context);
    }

    public List<WatchImportData> getCachedDataList() {
        return cachedDataList;
    }

    public String getMsg () {
            return msg;
        }

}
